package cn.rubintry.cardtest;

import android.content.Context;
import android.media.AudioManager;
import android.media.SoundPool;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

import com.app.tool.BytesUtil;
import com.app.tool.CharUtil;
import com.jiangdg.usbcamera.utils.Lf_Debug;
import com.lf.emv.jni;
import com.out.outdevice.RfidCtrl;
import com.out.outpara.ProductConfig;
import com.out.product.PRODUCT;
import com.out.transactioncallback.TransactionCallBack;

import java.util.List;


/***
 * @author logcat
 * 读卡器工具类
 */
public class IcCardReadUtils {

    private static final int START_READ_CARD = 1000;
    private static final int READ_SUCCESS = 1001;
    private static final int READ_FAIL = 1002;
    /**
     * 每次刷卡（或身份证）的时间间隔
     */
    private int TIME_DELAY = 10;

    private static volatile IcCardReadUtils instance;
    private String TAG = this.getClass().getSimpleName();
    private boolean curActivityExit;
    private SoundPool soundPool;
    private int music;
    private Context context;

    private Callback callback;
    private char[] data;
    private char[] cardId;
    private char[] keyChars;
    private CardReader cardReader;
    private long startRead;
    private boolean onlyIcCard;
    private boolean onlyIDCard;


    public IcCardReadUtils setCallback(Callback callback) {
        this.callback = callback;
        return this;
    }

    public void init(Context context) {
        this.context = context.getApplicationContext();
        curActivityExit = true;
        if (soundPool == null) {
            soundPool = new SoundPool(10, AudioManager.STREAM_SYSTEM, 5);
        }
        music = soundPool.load(this.context, R.raw.b, 1);

        cardReader = new CardReader();
        int ret = cardReader.open();
        Log.d(TAG, "cardReader: " + ret);

        data = new char[10];
        cardId = new char[16];
        keyChars = ScanUtils.getChars(ScanUtils.hexString2ByteArray("FFFFFFFFFFFF"));
        onlyIcCard = false;
        onlyIDCard = false;

    }

    public static IcCardReadUtils getInstance() {
        if (instance == null) {
            synchronized (IcCardReadUtils.class) {
                if (instance == null) {
                    instance = new IcCardReadUtils();
                }
            }
        }
        return instance;
    }


    /**
     * 开始执行读取线程
     */
    public void startRead() {

        new Thread(new Runnable() {
            @Override
            public void run() {
                read();
            }
        }).start();


    }


    /**
     * 读取卡片
     */
    private synchronized void read() {
        int ret = 0;
        char[] atr = new char[64];
        int rfidsucc = 0;
        int rfidfail = 0;

        jni.getInstance().rfid_close();
        ret = jni.getInstance().rfid_open(0);
        if (ret != 0) {
            Lf_Debug.dbg_mPrintf(Lf_Debug._FILE_LINE_FUNC_(), "射频卡打开失败");
            Message msgtext = new Message();
            msgtext.obj = "与读卡器通讯异常";
            msgtext.what = 2;
            mHandler.sendMessage(msgtext);
        }
        ret = jni.getInstance().rfid_version(atr);
        if (ret == 0) {
            byte[] ver = CharUtil.getBytes(atr);
            Lf_Debug.dbg_mPrintfWHex(Lf_Debug._FILE_LINE_FUNC_(), ver, 4, "版本号");
            String version;
            version = BytesUtil.byteArray2HexString(ver);
            Message msgtext = new Message();
            msgtext.obj = "版本号:" + version.substring(0, 8);
            msgtext.what = 2;
            mHandler.sendMessage(msgtext);
        }

        ret = RfidCtrl.getInstance().IdCardOpen();
        if (ret != 0) {
            Log.e(TAG, "身份证打开错误,请检查");
        }
        while (curActivityExit && cardReader != null) {
            Log.d(TAG, "正在读取: " + cardReader.hasCard());
            if (onlyIcCard) {
                readIcCardInfo(rfidsucc, rfidfail, atr);
            } else {
                if (onlyIDCard) {
                    readIDCardInfo(rfidsucc, rfidfail);
                } else {
                    readIcCardInfo(rfidsucc, rfidfail, atr);
                    readIDCardInfo(rfidsucc, rfidfail);
                }
            }
        }
    }

    private synchronized void readIcCardInfo(int rfidsucc, int rfidfail, char[] atr) {
        if (cardReader.hasCard() == 0) {
            Log.d(TAG, "准备读取IC卡: ");
            Message startReadMessage = new Message();
            startReadMessage.obj = "startReadCard";
            startReadMessage.what = START_READ_CARD;
            callBackHandler.sendMessage(startReadMessage);
//            if(callback != null){
//                callback.startReadCard();
//            }
            startRead = System.currentTimeMillis();
            //如果是IC卡，进入IC卡轮训
            RfidCtrl.getInstance().RfidClose();
            int ret;
            ret = RfidCtrl.getInstance().RfidOpen();
            if (ret != 0) {
                Log.d(TAG, "读卡器打开错误,请检查");
                Message msgrfidtext = new Message();
                msgrfidtext.obj = new String("读卡器打开错误,请检查");
                msgrfidtext.what = 3;
                mHandler.sendMessage(msgrfidtext);

            }

            ret = RfidCtrl.getInstance().RfidVersion(atr);
            if (ret == 0) {
                byte[] ver = CharUtil.getBytes(atr);
                Lf_Debug.dbg_mPrintfWHex(Lf_Debug._FILE_LINE_FUNC_(), ver, 4, "版本号");
                String version;
                version = BytesUtil.byteArray2HexString(ver);
                Message msgvertext = new Message();
                msgvertext.obj = "读卡器版本号:" + version.substring(0, 8);
                msgvertext.what = 3;
                mHandler.sendMessage(msgvertext);
                sys_DelayMs(1000);
            }

            rfidsucc = 0;
            rfidfail = 0;
            while (curActivityExit) {
                Message msgrfidtext = new Message();
                msgrfidtext.obj = "射频卡成功(" + Integer.toString(rfidsucc) + "次):" + "失败(" + Integer.toString(rfidfail) + "次):";
                msgrfidtext.what = 0;
                mHandler.sendMessage(msgrfidtext);

                sys_DelayMs(100);
                if (RfidCtrl.getInstance().testrfid(0)) {
                    Log.d(TAG, "读取成功: ");
                    if (callback != null) {
                        int code1 = cardReader.m1AuthKey(0, 1, keyChars);
                        int code2 = cardReader.m1Read(1, data);
                        int code3 = cardReader.m1Read(0, cardId);
                        byte[] date_cardId = new byte[16];
                        for (int i = 0; i < date_cardId.length; i++) {
                            date_cardId[i] = ((byte) (cardId[i] & 0xFF));
                        }

                        String cardIdStr = BytesUtil.getStrings(date_cardId).toUpperCase();
                        String cardNum = new String(data).substring(0, 6);
//                        callback.onSuccess(false, cardIdStr, cardNum, code1, code2, code3, null);
                        Result result = new Result(false, cardIdStr, cardNum, code1, code2, code3, null);
                        Message message = new Message();
                        message.what = READ_SUCCESS;
                        message.obj = result;
                        callBackHandler.sendMessage(message);
                        Log.d(TAG, "读取成功 , 耗时: " + (System.currentTimeMillis() - startRead) + "毫秒");
                        startRead = System.currentTimeMillis();
                    }
                    rfidsucc++;
                    soundPool.play(music, 1, 1, 1, 0, 1f);
                } else {
                    Log.d(TAG, "读取失败: ");
//                    if (callback != null) {
//                        callback.onFail();
//                    }
                    Message message = new Message();
                    message.what = READ_FAIL;
                    callBackHandler.sendMessage(message);
                    rfidfail++;
                    PRODUCT.getInstance().setConfigParam(ProductConfig.singlerfid, "1", setconfig);
                }
                if ("true".equals(PRODUCT.getInstance().getConfigParam(ProductConfig.testleexrfid))) {
                    sys_DelayMs(1000);
                    if (RfidCtrl.getInstance().testrfid2(0)) {
                        rfidsucc++;
                        soundPool.play(music, 1, 1, 1, 0, 1f);
                        if (callback != null) {
                            int code1 = cardReader.m1AuthKey(0, 1, keyChars);
                            int code2 = cardReader.m1Read(1, data);
                            int code3 = cardReader.m1Read(0, cardId);
                            byte[] date_cardId = new byte[16];
                            for (int i = 0; i < date_cardId.length; i++) {
                                date_cardId[i] = ((byte) (cardId[i] & 0xFF));
                            }

                            String cardIdStr = BytesUtil.getStrings(date_cardId).toUpperCase();
                            String cardNum = new String(data).substring(0, 6);
//                            callback.onSuccess(false, cardIdStr, cardNum, code1, code2, code3, null);
                            Result result = new Result(false, cardIdStr, cardNum, code1, code2, code3, null);
                            Message message = new Message();
                            message.what = READ_SUCCESS;
                            message.obj = result;
                            callBackHandler.sendMessage(message);
                            Log.d(TAG, "读取成功 , 耗时: " + (System.currentTimeMillis() - startRead) + "毫秒");
                            startRead = System.currentTimeMillis();
                        }
                    } else {
                        rfidfail++;
                        Log.d(TAG, "读取失败: ");
//                        if (callback != null) {
//                            callback.onFail();
//                        }
                        Message message = new Message();
                        message.what = READ_FAIL;
                        callBackHandler.sendMessage(message);

                    }
                }
                break;
            }

        }
    }

    private synchronized void readIDCardInfo(int rfidsucc, int rfidfail) {

        if (cardReader.hasCard() == 1) {
            //身份证
            Log.d(TAG, "开始读取身份证");
            startRead = System.currentTimeMillis();

            Message startReadMessage = new Message();
            startReadMessage.what = START_READ_CARD;
            startReadMessage.obj = "startReadCard";
            callBackHandler.sendMessage(startReadMessage);

            startRead = System.currentTimeMillis();
            sys_DelayMs(TIME_DELAY);


            if (RfidCtrl.getInstance().testrfid(1)) {
                rfidsucc++;
                if (soundPool != null) {
                    soundPool.play(music, 1, 1, 1, 0, 1f);
                }

                if (RfidCtrl.getIdready() == 1) {
                    Bundle idinfo = RfidCtrl.getIdInfo();
                    //获取身份证号码
                    String cardNum = idinfo.getString("id_no");
                    String name = idinfo.getString("id_name").replaceAll(" ", "");
                    if (callback != null) {
                        Result result = new Result(true, null, cardNum, 0, 0, 0, name);
                        Message message = new Message();
                        message.what = READ_SUCCESS;
                        message.obj = result;
                        callBackHandler.sendMessage(message);
                        Log.d(TAG, "读取成功 , 耗时: " + (System.currentTimeMillis() - startRead) + "毫秒");
                        startRead = System.currentTimeMillis();
                    }
//                    sys_DelayMs(1000);
                }
            } else {
                rfidfail++;
                Log.e(TAG, "读取身份证出错: ");
//                if(callback != null){
//                    callback.onFail();
//                }
                Message message = new Message();
                message.what = READ_FAIL;
                callBackHandler.sendMessage(message);
            }

        }else if (cardReader.hasCard() == -1) {
            if (RfidCtrl.getInstance().testrfid(1)) {
                Message startReadMessage = new Message();
                startReadMessage.what = START_READ_CARD;
                startReadMessage.obj = "startReadCard";
                callBackHandler.sendMessage(startReadMessage);

                rfidsucc++;
                soundPool.play(music, 1, 1, 1, 0, 1f);
                if (RfidCtrl.getIdready() == 1) {
                    Bundle idinfo = RfidCtrl.getIdInfo();
                    //获取身份证号码
                    String cardNum = idinfo.getString("id_no");
                    String name = idinfo.getString("id_name").replaceAll(" ", "");
//                    if (callback != null) {
//                        callback.onSuccess(true, null, cardNum, 0, 0, 0, name);
//                        Log.d(TAG, "读取成功 , 耗时: " + (System.currentTimeMillis() - startRead) + "毫秒");
//                        startRead = System.currentTimeMillis();
//                    }
                    Result result = new Result(true , null , cardNum , 0 , 0 , 0 , name);
                    Message message = new Message();
                    message.what = READ_SUCCESS;
                    message.obj = result;
                    callBackHandler.sendMessage(message);
                }
            }
        }
    }

    private void sys_DelayMs(int duration_ms) {
        try {
            Thread.sleep(duration_ms);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }


    Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            Lf_Debug.dbg_mPrintf(Lf_Debug._FILE_LINE_FUNC_(), (String) msg.obj);
            switch (msg.what) {
                case 0:
//                    //成功

                case 3:
//                    //读卡器打开错误
                    break;
                case 1:
                    break;
                case 2:
                    //版本号
                    break;
                default:
                    break;
            }
        }
    };


    TransactionCallBack setconfig = new TransactionCallBack() {
        @Override
        public void processMsg(List<String> arg0) {
        }

        @Override
        public void onSuccess(String successInfo, Bundle bundle) {
            Lf_Debug.dbg_mPrintf(Lf_Debug._FILE_LINE_FUNC_(), "---------setConfigParams------" + successInfo);
        }

        @Override
        public void onError(int errorCode, Bundle bundle) {
            Lf_Debug.dbg_mPrintf(Lf_Debug._FILE_LINE_FUNC_(), "---------setConfigParams------" + bundle.getString("errorInfo"));
        }
    };

    public void setOnlyIcCard(boolean onlyIcCard) {
        this.onlyIcCard = onlyIcCard;
    }

    public void setOnlyIDCard(boolean onlyIDCard) {
        this.onlyIDCard = onlyIDCard;
    }


    public interface Callback {

        void startReadCard();

        /**
         * 读取成功
         *
         * @param isIdCard
         * @param cardId
         * @param cardNum
         * @param errorCode1
         * @param errorCode2
         * @param errorCode3
         * @param name
         */
        void onSuccess(boolean isIdCard, String cardId, String cardNum, int errorCode1, int errorCode2, int errorCode3, String name);

        /**
         * 读取失败
         */
        void onFail();
    }


    public void release() {
        if (curActivityExit) {
            curActivityExit = false;
            cardReader.close();
            soundPool.release();
            soundPool = null;
        }
        callback = null;
    }

    public void stop() {
        curActivityExit = false;
        callback = null;
    }

    private class Result {
        private boolean isIdCard;
        private String cardId;
        private String cardNum;
        private int errorCode1;
        private int errorCode2;
        private int errorCode3;
        private String name;

        public Result(boolean isIdCard, String cardId, String cardNum, int errorCode1, int errorCode2, int errorCode3, String name) {
            this.isIdCard = isIdCard;
            this.cardId = cardId;
            this.cardNum = cardNum;
            this.errorCode1 = errorCode1;
            this.errorCode2 = errorCode2;
            this.errorCode3 = errorCode3;
            this.name = name;
        }

        public boolean isIdCard() {
            return isIdCard;
        }

        public void setIdCard(boolean idCard) {
            isIdCard = idCard;
        }

        public String getCardId() {
            return cardId;
        }

        public void setCardId(String cardId) {
            this.cardId = cardId;
        }

        public String getCardNum() {
            return cardNum;
        }

        public void setCardNum(String cardNum) {
            this.cardNum = cardNum;
        }

        public int getErrorCode1() {
            return errorCode1;
        }

        public void setErrorCode1(int errorCode1) {
            this.errorCode1 = errorCode1;
        }

        public int getErrorCode2() {
            return errorCode2;
        }

        public void setErrorCode2(int errorCode2) {
            this.errorCode2 = errorCode2;
        }

        public int getErrorCode3() {
            return errorCode3;
        }

        public void setErrorCode3(int errorCode3) {
            this.errorCode3 = errorCode3;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }
    }


    Handler callBackHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case START_READ_CARD:
                    if (callback != null) {
                        callback.startReadCard();
                    }
                    break;
                case READ_SUCCESS:
                    Result result = (Result) msg.obj;
                    callback.onSuccess(result.isIdCard(), result.getCardId(), result.getCardNum(), result.getErrorCode1(), result.getErrorCode2(), result.getErrorCode3(), result.getName());
                    break;
                case READ_FAIL:
                    if (callback != null) {
                        callback.onFail();
                    }
                    break;
                default:
                    break;
            }
        }
    };

}